package com.lifeonwalden.game.mindustry.entity;

import com.badlogic.gdx.graphics.g2d.Batch;
import com.lifeonwalden.game.mindustry.constant.*;
import com.lifeonwalden.game.mindustry.model.ConveyorProperty;

import java.util.Optional;

public class Conveyor extends StaticEntity {
    public StaticEntity[] exporter = new StaticEntity[3];
    public StaticEntity taker;
    public ResourceType[] resources = new ResourceType[4];
    public long timeCounter = 0;

    public Conveyor() {
        this.toward = Toward.RIGHT;
        this.league = League.Pathfinder;
        this.hp = this.type.maxHp;
    }

    @Override
    public void joinExporter(StaticEntity unit, Gate at) {
        switch (this.toward) {
            case UP: {
                switch (at) {
                    case RIGHT: {
                        this.exporter[0] = unit;
                        return;
                    }
                    case BOTTOM: {
                        this.exporter[1] = unit;
                        return;
                    }
                    case LEFT: {
                        this.exporter[2] = unit;
                        return;
                    }
                }
                break;
            }
            case RIGHT: {
                switch (at) {
                    case BOTTOM: {
                        this.exporter[0] = unit;
                        return;
                    }
                    case LEFT: {
                        this.exporter[1] = unit;
                        return;
                    }
                    case UP: {
                        this.exporter[2] = unit;
                        return;
                    }
                }
                break;
            }
            case BOTTOM: {
                switch (at) {
                    case LEFT: {
                        this.exporter[0] = unit;
                        return;
                    }
                    case UP: {
                        this.exporter[1] = unit;
                        return;
                    }
                    case RIGHT: {
                        this.exporter[2] = unit;
                        return;
                    }
                }
                break;
            }
            case LEFT: {
                switch (at) {
                    case UP: {
                        this.exporter[0] = unit;
                        return;
                    }
                    case RIGHT: {
                        this.exporter[1] = unit;
                        return;
                    }
                    case BOTTOM: {
                        this.exporter[2] = unit;
                        return;
                    }
                }
                break;
            }
        }
    }

    @Override
    public void join(StaticEntity unit, Gate at) {
        switch (this.toward) {
            case UP: {
                switch (at) {
                    case UP: {
                        this.taker = unit;
                        return;
                    }
                }
                break;
            }
            case RIGHT: {
                switch (at) {
                    case RIGHT: {
                        this.taker = unit;
                        return;
                    }
                }
                break;
            }
            case BOTTOM: {
                switch (at) {
                    case BOTTOM: {
                        this.taker = unit;
                        return;
                    }
                }
                break;
            }
            case LEFT: {
                switch (at) {
                    case LEFT: {
                        this.taker = unit;
                        return;
                    }
                }
                break;
            }
        }
    }

    @Override
    public void unjoin(Gate at) {
        switch (this.toward) {
            case UP: {
                switch (at) {
                    case UP: {
                        this.taker = null;
                        return;
                    }
                    case RIGHT: {
                        this.exporter[0] = null;
                        return;
                    }
                    case BOTTOM: {
                        this.exporter[1] = null;
                        return;
                    }
                    case LEFT: {
                        this.exporter[2] = null;
                        return;
                    }
                }
                break;
            }
            case RIGHT: {
                switch (at) {
                    case RIGHT: {
                        this.taker = null;
                        return;
                    }
                    case BOTTOM: {
                        this.exporter[0] = null;
                        return;
                    }
                    case LEFT: {
                        this.exporter[1] = null;
                        return;
                    }
                    case UP: {
                        this.exporter[2] = null;
                        return;
                    }
                }
                break;
            }
            case BOTTOM: {
                switch (at) {
                    case BOTTOM: {
                        this.taker = null;
                        return;
                    }
                    case LEFT: {
                        this.exporter[0] = null;
                        return;
                    }
                    case UP: {
                        this.exporter[1] = null;
                        return;
                    }
                    case RIGHT: {
                        this.exporter[2] = null;
                        return;
                    }
                }
                break;
            }
            case LEFT: {
                switch (at) {
                    case LEFT: {
                        this.taker = null;
                        return;
                    }
                    case UP: {
                        this.exporter[0] = null;
                        return;
                    }
                    case RIGHT: {
                        this.exporter[1] = null;
                        return;
                    }
                    case BOTTOM: {
                        this.exporter[2] = null;
                        return;
                    }
                }
                break;
            }
        }
    }

    @Override
    public PorterType porterAt(Gate gate) {
        switch (this.toward) {
            case UP: {
                switch (gate) {
                    case UP: {
                        return PorterType.EXPORTER;
                    }
                    default: {
                        return PorterType.TAKER;
                    }
                }
            }
            case RIGHT: {
                switch (gate) {
                    case RIGHT: {
                        return PorterType.EXPORTER;
                    }
                    default: {
                        return PorterType.TAKER;
                    }
                }
            }
            case BOTTOM: {
                switch (gate) {
                    case BOTTOM: {
                        return PorterType.EXPORTER;
                    }
                    default: {
                        return PorterType.TAKER;
                    }
                }
            }
            case LEFT: {
                switch (gate) {
                    case LEFT: {
                        return PorterType.EXPORTER;
                    }
                    default: {
                        return PorterType.TAKER;
                    }
                }
            }
        }
        return PorterType.CLOSED;
    }

    @Override
    public Optional<ResourceType> take() {
        if (null != resources[0]) {
            ResourceType resource = resources[0];
            resources[0] = null;
            return Optional.of(resource);
        } else {
            return Optional.empty();
        }
    }

    @Override
    public Optional<ResourceType> checkResourceAcceptable() {
        if (null != resources[0]) {
            return Optional.of(resources[0]);
        } else {
            return Optional.empty();
        }
    }

    @Override
    public void doJobBefore() {
        long now = System.currentTimeMillis();
        if (now > timeCounter) {
            if (null == resources[0]) {
                resources[0] = resources[1];
                resources[1] = null;
            }

            if (null == resources[1]) {
                Optional<ResourceType> resource = null != this.exporter[0] ? this.exporter[0].take() : Optional.empty();
                if (!resource.isPresent()) {
                    resource = null != this.exporter[2] ? this.exporter[2].take() : Optional.empty();
                }
                if (resource.isPresent()) {
                    resources[1] = resource.get();
                } else {
                    resources[1] = resources[2];
                    resources[2] = null;
                }
            }
            if (null == resources[2]) {
                Optional<ResourceType> resource = null != this.exporter[0] ? this.exporter[0].take() : Optional.empty();
                if (!resource.isPresent()) {
                    resource = null != this.exporter[2] ? this.exporter[2].take() : Optional.empty();
                }
                if (resource.isPresent()) {
                    resources[2] = resource.get();
                } else {
                    resources[2] = resources[3];
                    resources[3] = null;
                }
            }

            if (null == resources[3]) {
                Optional<ResourceType> resource = null != this.exporter[1] ? this.exporter[1].take() : Optional.empty();
                if (resource.isPresent()) {
                    resources[3] = resource.get();
                }
            }

            timeCounter = now + ((ConveyorProperty) this.type.property.property()).speed;
        }
    }

    @Override
    public void draw(Batch batch) {
        switch (this.toward) {
            case UP: {
                int width = this.type.texture.getRegionWidth(), height = this.type.texture.getRegionHeight();
                batch.draw(this.type.texture, this.x, this.y, width / 2, height / 2, width, height, 1f, 1f, 90);
                for (int i = 0; i < resources.length; i++) {
                    if (null != resources[i]) {
                        batch.draw(resources[i].texture, this.x + 3, this.y + 6 - i * 2, 1, 1, 2, 2, 1, 1, 90);
                    }
                }

                break;
            }
            case RIGHT: {
                batch.draw(this.type.texture, this.x, this.y);
                for (int i = 0; i < resources.length; i++) {
                    if (null != resources[i]) {
                        batch.draw(ResourceType.Stone.texture, this.x + 6 - i * 2, this.y + 3, 2, 2);
                    }
                }
                break;
            }
            case BOTTOM: {
                int width = this.type.texture.getRegionWidth(), height = this.type.texture.getRegionHeight();
                batch.draw(this.type.texture, this.x, this.y, width / 2, height / 2, width, height, 1f, 1f, 90);
                for (int i = 0; i < resources.length; i++) {
                    if (null != resources[i]) {
                        batch.draw(resources[i].texture, this.x + 3, this.y + i * 2, 1, 1, 2, 2, 1, 1, 90);
                    }
                }

                break;
            }
            case LEFT: {
                batch.draw(this.type.texture, this.x, this.y);
                for (int i = 0; i < resources.length; i++) {
                    if (null != resources[i]) {
                        batch.draw(ResourceType.Stone.texture, this.x + i * 2, this.y + 3, 2, 2);
                    }
                }
            }
        }
    }

    @Override
    public Surface copy(boolean deep) {
        Conveyor newOne = (Conveyor) super.copy(deep);
        if (!deep) {
            newOne.exporter = new StaticEntity[3];
            newOne.taker = null;
            newOne.resources = new ResourceType[4];
        }
        return newOne;
    }

    @Override
    public void destroy() {
        switch (this.toward) {
            case UP: {
                if (null != this.taker) {
                    this.taker.unjoin(Gate.UP.linkedGate());
                }
                if (null != this.exporter[0]) {
                    this.exporter[0].unjoin(Gate.RIGHT.linkedGate());
                }
                if (null != this.exporter[1]) {
                    this.exporter[1].unjoin(Gate.BOTTOM.linkedGate());
                }
                if (null != this.exporter[2]) {
                    this.exporter[2].unjoin(Gate.LEFT.linkedGate());
                }
                break;
            }
            case RIGHT: {
                if (null != this.taker) {
                    this.taker.unjoin(Gate.RIGHT.linkedGate());
                }
                if (null != this.exporter[0]) {
                    this.exporter[0].unjoin(Gate.BOTTOM.linkedGate());
                }
                if (null != this.exporter[1]) {
                    this.exporter[1].unjoin(Gate.LEFT.linkedGate());
                }
                if (null != this.exporter[2]) {
                    this.exporter[2].unjoin(Gate.UP.linkedGate());
                }
                break;
            }
            case BOTTOM: {
                if (null != this.taker) {
                    this.taker.unjoin(Gate.BOTTOM.linkedGate());
                }
                if (null != this.exporter[0]) {
                    this.exporter[0].unjoin(Gate.LEFT.linkedGate());
                }
                if (null != this.exporter[1]) {
                    this.exporter[1].unjoin(Gate.UP.linkedGate());
                }
                if (null != this.exporter[2]) {
                    this.exporter[2].unjoin(Gate.RIGHT.linkedGate());
                }
                break;
            }
            case LEFT: {
                if (null != this.taker) {
                    this.taker.unjoin(Gate.LEFT.linkedGate());
                }
                if (null != this.exporter[0]) {
                    this.exporter[0].unjoin(Gate.UP.linkedGate());
                }
                if (null != this.exporter[1]) {
                    this.exporter[1].unjoin(Gate.RIGHT.linkedGate());
                }
                if (null != this.exporter[2]) {
                    this.exporter[2].unjoin(Gate.BOTTOM.linkedGate());
                }
                break;
            }
        }
    }
}
